package com.demo.java.OD401_450.OD401;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author bug菌
 * @Source 公众号：猿圈奇妙屋
 * @des： 【数组中第 K 大的数中的最小值(C&D卷-200分)】问题
 * @url： https://blog.csdn.net/weixin_43970743/article/details/146249876
 */
public class OdMain {
    static final int N = 255;
    static final long INF = Long.MAX_VALUE;
    static int m, n, k;  // m为二分图右侧节点数，n为左侧节点数，k为需要删除的边数

    static boolean[] vis = new boolean[N];  // 记录右侧节点是否已被访问
    static boolean[][] line = new boolean[N][N];  // 邻接矩阵表示图的边
    static int[] row = new int[N];  // 记录右侧节点匹配到的左侧节点
    static int[][] w = new int[N][N];  // 存储图的权重

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();  // 左侧节点数
        m = sc.nextInt();  // 右侧节点数
        k = sc.nextInt();  // 需要删除的边数

        // 图的权重
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                w[i][j] = sc.nextInt();
            }
        }

        long l = 1, r = INF, ans = 0;

        // 二分查找最大权重，满足匹配数大于等于左侧节点数减去需要删除的边数
        while (l <= r) {
            long mid = (l + r) / 2;
            if (check(mid)) {
                r = mid - 1;
                ans = mid;
            } else {
                l = mid + 1;
            }
        }
        System.out.println(ans);  // 输出最大权重
    }

    // 查找增广路径
    static boolean find(int x) {
        for (int i = 1; i <= m; ++i) {
            if (line[x][i] && !vis[i]) {
                vis[i] = true;
                if (row[i] == 0 || find(row[i])) {
                    row[i] = x;
                    return true;
                }
            }
        }
        return false;
    }

    // 根据权重限制重建图的边
    static void rebuild(long limit) {
        for (boolean[] booleans : line) {
            Arrays.fill(booleans, false);
        }
        Arrays.fill(row, 0);

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (w[i][j] <= limit) {
                    line[i][j] = true;
                }
            }
        }
    }

    // 检查是否存在匹配数大于等于左侧节点数减去需要删除的边数
    static boolean check(long x) {
        rebuild(x);
        int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            Arrays.fill(vis, false);
            if (find(i)) {
                ++cnt;
            }
        }
        return cnt > n - k;
    }
}